//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/api_common"
	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_api"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *BoardApiImpl) Create(ctx context.Context, req *board_api.CreateRequest) (*board_api.CreateResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.CreateResponse{
			Code:   board_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	boardId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.CreateBoard(sessCtx, &board_dao.BoardInfoDbItem{
			BoardId: boardId,
			BasicInfo: board_dao.BasicBoardInfoDbItem{
				BoardName: req.BasicInfo.BoardName,
			},
			NodePanelSetting: board_dao.NodePanelSettingDbItem{
				ShowSvgNode:   false,
				ShowImageNode: false,
				ShowLinkNode:  false,
				ShowDevelop:   false,
			},
			ImageFsId:  uuid.NewString(),
			CreateTime: nowTime,
			UpdateTime: nowTime,
		}, sessItem.UserId)
		if err != nil {
			return nil, err
		}
		return &board_api.CreateResponse{
			Code:    board_api.CreateResponse_CODE_OK,
			BoardId: boardId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(boardId, &notices_board.CreateBoardNotice{
		BoardId: boardId,
	})
	return ret.(*board_api.CreateResponse), nil
}

func (apiImpl *BoardApiImpl) UpdateBasic(ctx context.Context, req *board_api.UpdateBasicRequest) (*board_api.UpdateBasicResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.UpdateBasicResponse{
			Code:   board_api.UpdateBasicResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	//检查board成员权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_api.UpdateBasicResponse{
			Code:   board_api.UpdateBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_api.UpdateBasicResponse{
			Code:   board_api.UpdateBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.BoardInfoDao.UpdateBasic(sessCtx, req.BoardId, &board_dao.BasicBoardInfoDbItem{
			BoardName: req.BasicInfo.BoardName,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_api.UpdateBasicResponse{
			Code: board_api.UpdateBasicResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateBoardNotice{
		BoardId: req.BoardId,
	})
	return ret.(*board_api.UpdateBasicResponse), nil
}

func (apiImpl *BoardApiImpl) UpdateNodePanelSetting(ctx context.Context, req *board_api.UpdateNodePanelSettingRequest) (*board_api.UpdateNodePanelSettingResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.UpdateNodePanelSettingResponse{
			Code:   board_api.UpdateNodePanelSettingResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	//检查board成员权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_api.UpdateNodePanelSettingResponse{
			Code:   board_api.UpdateNodePanelSettingResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_api.UpdateNodePanelSettingResponse{
			Code:   board_api.UpdateNodePanelSettingResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.BoardInfoDao.UpdateNodePanelSetting(sessCtx, req.BoardId, &board_dao.NodePanelSettingDbItem{
			ShowSvgNode:   req.NodePanelSetting.ShowSvgNode,
			ShowImageNode: req.NodePanelSetting.ShowImageNode,
			ShowLinkNode:  req.NodePanelSetting.ShowLinkNode,
			ShowDevelop:   req.NodePanelSetting.ShowDevelop,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_api.UpdateNodePanelSettingResponse{
			Code: board_api.UpdateNodePanelSettingResponse_CODE_OK,
		}, nil
	})
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateBoardNotice{
		BoardId: req.BoardId,
	})
	return ret.(*board_api.UpdateNodePanelSettingResponse), nil
}

func (apiImpl *BoardApiImpl) Remove(ctx context.Context, req *board_api.RemoveRequest) (*board_api.RemoveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.RemoveResponse{
			Code:   board_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查画板是否存在
	exist, err := board_dao.BoardInfoDao.Exist(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_api.RemoveResponse{
			Code: board_api.RemoveResponse_CODE_OK,
		}, nil
	}
	//检查board成员权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_api.RemoveResponse{
			Code:   board_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_api.RemoveResponse{
			Code:   board_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//获取当前board所有成员
	memberUserIdList, err := board_dao.MemberInfoDao.DistinctMemberUserId(ctx, req.BoardId, false, []string{})
	if err != nil {
		return nil, err
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.RemoveBoard(sessCtx, req.BoardId)
		if err != nil {
			return nil, err
		}
		return &board_api.RemoveResponse{
			Code: board_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go func() {
		for _, memberUserId := range memberUserIdList {
			notice_serv.PublishToUser(memberUserId, &notices_board.RemoveBoardNotice{
				BoardId: req.BoardId,
			})
		}
	}()
	return ret.(*board_api.RemoveResponse), nil
}

func (apiImpl *BoardApiImpl) ListMy(ctx context.Context, req *board_api.ListMyRequest) (*board_api.ListMyResponse, error) {
	emptyList := []*board_api.BoardInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.ListMyResponse{
			Code:      board_api.ListMyResponse_CODE_WRONG_SESSION,
			ErrMsg:    "会话不存在",
			BoardList: emptyList,
		}, nil
	}
	boardIdList, err := board_dao.MemberInfoDao.DistinctBoardId(ctx, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	boardItemList, err := board_dao.BoardInfoDao.ListById(ctx, boardIdList)
	if err != nil {
		return nil, err
	}
	boardList, err := apiImpl.convertToBoardList(ctx, boardItemList, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	return &board_api.ListMyResponse{
		Code:      board_api.ListMyResponse_CODE_OK,
		BoardList: boardList,
	}, nil
}

func (apiImpl *BoardApiImpl) Get(ctx context.Context, req *board_api.GetRequest) (*board_api.GetResponse, error) {
	emptyInfo := &board_api.BoardInfo{
		BasicInfo: &board_api.BasicBoardInfo{},
		UserPerm:  &board_api.UserPerm{},
		LlmList:   []*board_api.LlmInfo{},
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_api.GetResponse{
			Code:   board_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Board:  emptyInfo,
		}, nil
	}

	//检查成员权限
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_api.GetResponse{
			Code:   board_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Board:  emptyInfo,
		}, nil
	}

	boardItem, err := board_dao.BoardInfoDao.Get(ctx, req.BoardId)
	if err != nil {
		return &board_api.GetResponse{
			Code:   board_api.GetResponse_CODE_NO_BOARD,
			ErrMsg: "画板不存在",
			Board:  emptyInfo,
		}, nil
	}
	boardList, err := apiImpl.convertToBoardList(ctx, []*board_dao.BoardInfoDbItem{boardItem}, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if len(boardList) == 0 {
		return &board_api.GetResponse{
			Code:   board_api.GetResponse_CODE_NO_BOARD,
			ErrMsg: "画板不存在",
			Board:  emptyInfo,
		}, nil
	}
	return &board_api.GetResponse{
		Code:  board_api.GetResponse_CODE_OK,
		Board: boardList[0],
	}, nil
}

func (apiImpl *BoardApiImpl) convertToBoardList(ctx context.Context, boardItemList []*board_dao.BoardInfoDbItem, memberUserId string) ([]*board_api.BoardInfo, error) {
	boardIdList := []string{}
	for _, boardItem := range boardItemList {
		boardIdList = append(boardIdList, boardItem.BoardId)
	}

	//获取画板成员权限
	memberItemList, err := board_dao.MemberInfoDao.ListByMember(ctx, memberUserId, true, boardIdList)
	if err != nil {
		return nil, err
	}
	boardAdminMap := map[string]bool{}
	for _, memberItem := range memberItemList {
		boardAdminMap[memberItem.BoardId] = memberItem.Admin
	}
	//列出所有llm配置
	llmItemList, err := board_dao.BoardLlmDao.ListByBoard(ctx, boardIdList)
	if err != nil {
		return nil, err
	}

	//生成数据
	boardList := []*board_api.BoardInfo{}
	for _, boardItem := range boardItemList {
		board := boardItem.ToBoardInfo()
		board.UserPerm = &board_api.UserPerm{
			CanUpdate: boardAdminMap[boardItem.BoardId],
			CanRemove: boardAdminMap[boardItem.BoardId],
		}
		for _, llmItem := range llmItemList {
			if llmItem.BoardId == boardItem.BoardId {
				board.LlmList = append(board.LlmList, llmItem.ToLlmInfo())
			}
		}

		boardList = append(boardList, board)
	}
	return boardList, nil
}
